package com.mybatis.plug.slicingStrategy;


import com.mybatis.plug.util.ApplicationContextUtil;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by
 *
 * @author admin
 * @date 2018/11/24
 */
public abstract class AbstratStrategy implements Strategy {
    //兼容log4j记录机制,不能使用logger记录自身
    //log4j日志入库
    //private static final Logger logger = LoggerFactory.getLogger(AbstratStrategy.class);

    private static ConcurrentHashMap<String, Boolean> cacheMap = new ConcurrentHashMap<String, Boolean>();

    protected static DataSource ds = null;
    protected Connection connection = null;

    public void getDs() {
        //要兼容log4j特殊启动日志
        //update  log4j append兼容:过滤掉系统启动中日志.等spring完全启动完毕才开始记录日志
        if (null == ds) {
            if (!ApplicationContextUtil.isStart()) {
                return;
            }
            ds = (DataSource) ApplicationContextUtil.getContext().getBean("DataSource");
        }
    }

    @Override
    public void run(String tableNameBase, String tableNameNew) {
        //统一处理调度
        try {
            boolean maketable = !tableExist(tableNameNew);

            if (maketable) {
                createTable(tableNameBase, tableNameNew);
            }
        } catch (Exception e) {
            System.err.println("按切割表策略创建新表过程异常");
            e.printStackTrace();
        }
    }


    private boolean tableExist(String tableName) {
        Boolean cacheTableName = getCache(tableName);
        if (cacheTableName) {
            return true;
        }
        String sql = "select count(*) from user_tables where table_name = ?";
        Connection con = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        Integer count = 0;
        try {
            con = getConnection();
            if (null == con) {
                return false;
            }
            stmt = con.prepareStatement(sql);
            stmt.setString(1, tableName);
            rs = stmt.executeQuery();
            if (rs.next()) {
                count = rs.getInt(1);
            }
        } catch (Exception e) {
            System.err.println(e.getMessage() + " " + sql);
            e.printStackTrace();
        } finally {
            if (stmt != null)
                try {
                    stmt.close();
                    stmt.close();
                    closeConnection(con);
                } catch (Exception e) {
                }
        }

        if (count == 0) {
            return false;
        } else {
            // 如果该表已经存在 缓存
            initCache(tableName);
            return true;
        }
    }

    private boolean createTable(String tableNameBase, String tableNameNew) {
        String sql = "create table " + tableNameNew + " as select * from " + tableNameBase + " where 1=2";
        Connection con = null;
        PreparedStatement stmt = null;
        try {
            con = getConnection();
            if (null == con) {
                return false;
            }
            stmt = con.prepareStatement(sql);
            // stmt.setString(1, tableNameNew);
            //stmt.setString(2, tableNameBase);
            stmt.executeUpdate();
        } catch (Exception e) {
            System.err.println(e.getMessage() + " " + sql);
            e.printStackTrace();
        } finally {
            if (stmt != null)
                try {
                    stmt.close();
                    stmt.close();
                    closeConnection(con);
                } catch (Exception e) {
                }
        }
        return true;
    }

    protected Connection getConnection() throws SQLException {
        //系统启动前日志
        if (null == ds) {
            getDs();
        }
        if (connection == null) {
            connection = ds.getConnection();
        }

        return connection;
    }

    protected void closeConnection(Connection con) {
    }

    private final Boolean getCache(String tableName) {
        // 如果缓冲中有该表，则返回value
        if (cacheMap.containsKey(tableName)) {
            return cacheMap.get(tableName);
        } else {
            return false;
        }
    }

    private final void initCache(String tableName) {
        // 一般是进行数据库查询，将查询的结果进行缓存
        cacheMap.put(tableName, true);
    }

    private final void removeCache(String tableName) {
        cacheMap.remove(tableName);
    }
}
